package org.box.metadata.shell.web.servlet;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.buffer.CircularFifoBuffer;
import org.box.metadata.cli.annotation.Command;
import org.box.metadata.shell.CommandHandler;
import org.box.metadata.shell.CommandHandlerListener;
import org.box.metadata.shell.web.LogRecord;
import org.box.metadata.shell.web.WebConsoleCallback;
import org.box.metadata.shell.web.WebShell;

import com.fasterxml.jackson.databind.ObjectMapper;

public abstract class ConsoleCallbackServlet extends HttpServlet implements CommandHandlerListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private final static Logger LOG = Logger.getLogger(ConsoleCallbackServlet.class.getName());
	
	private final ByteArrayOutputStream outContent;
	
	public static final String LAST_INDEX_PARAM = "li";
	
	private long rowindex;
	
	private final CircularFifoBuffer buffer;

	protected final WebShell shell;
	
	private final ObjectMapper jsonMapper = new ObjectMapper();
	
	public ConsoleCallbackServlet(WebShell shell, ByteArrayOutputStream outContent, int bufferSize) {
		this.shell = shell;
		this.outContent = outContent;
		buffer = new CircularFifoBuffer(bufferSize);
		shell.addListener(this);
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		resp.setContentType("application/json; charset=utf-8");
		resp.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1
		resp.setHeader("Pragma", "no-cache"); // HTTP 1.0
		resp.setDateHeader("Expires", 0); // Proxies.
		
		updatedBuffer(shell.getCurrentSession()); 
		jsonMapper.writeValue(resp.getOutputStream(), createCallback(req, buffer));
	}

	protected abstract WebConsoleCallback createCallback(HttpServletRequest req, CircularFifoBuffer buffer);

	protected void updatedBuffer(String session) {
		String[] lines = null;
        synchronized (outContent) {
        	String str = outContent.toString();
        	if (str.length() > 0)
        		lines = outContent.toString().split("\n");
	        outContent.reset();
        }
	        
        if (lines != null)
	        for (String msg : lines) {
	        	if (LOG.isLoggable(Level.FINE))
	        		LOG.fine("Session: " + session + "; " + msg);
	        	buffer.add(new LogRecord(rowindex++, msg, session));
	        }
        
	}

	protected int getLastIndex(HttpServletRequest request, String session) {
		String liStr = request.getParameter(LAST_INDEX_PARAM);
		if (liStr != null) {
			try {
				return Integer.parseInt(liStr);
			} catch (Exception e) {
	        	if (LOG.isLoggable(Level.WARNING))
	        		LOG.warning("Session: " + session + "; Invalid prameter LI: " + liStr);
			}
		}
		return -1;
	}

	@Override
	public void onHandlerStart(CommandHandler<?> handler, Command c, Object cfg) {
		
	}

	@Override
	public void onHandlerSuccess(CommandHandler<?> handler, Command c, Object cfg){
		updatedBuffer(shell.getCurrentSession());
	}
	
	@Override
	public void onHandlerFailure(CommandHandler<?> handler, Command c, Object cfg){
		updatedBuffer(shell.getCurrentSession());
	}


}
